﻿using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Movement))]
[RequireComponent(typeof(SphereCollider))]

public class AI : MonoBehaviour {
	private enum State
	{
		Init,					//Do nothing
		Idle,					//Make sure that everything we need is here
		Setup,					//assign the values to the things we need
		Search,					//find the player
		Decide,					//Decide what to do with the targetter player
	}
	public float perceptionRadius = 10; // range that enemy can detect character at


	private Transform _target;

	private Transform _myTransform;

	private const float _ROTATION_DAMP = 0.3f;
	private const float _FORWARD_DAMP = 0.9f;

	private Transform _home;

	private State _state;

	private SphereCollider _sphereCollider;

	private MobBrain _me;

	void Awake(){
		_me = gameObject.GetComponent<MobBrain>();
	}
	// Use this for initialization
	void Start () {
		_state = AI.State.Init;
		StartCoroutine ("FSM");

	}

	private IEnumerator FSM(){
//		Debug.Log("FSM");
		while (_state != AI.State.Idle) {
			switch(_state){
			case State.Init:
				Init();
				break;
			case State.Setup:
				Setup();
				break;
			case State.Search:
				Search();
				break;
			case State.Decide:
				Decide();
				break;
			}
			yield return null;
		}
	}

	private void Init(){
		_myTransform = transform;
		_home = transform.parent.transform;
		_sphereCollider = GetComponent<SphereCollider> ();

		if (_sphereCollider == null) {
			Debug.LogError("SphereCollider Not Present");
			return;
		}
		_state = AI.State.Setup;
	}

	private void Setup(){
		_sphereCollider.center = GetComponent<CharacterController> ().center;
		_sphereCollider.radius = perceptionRadius;
		_sphereCollider.isTrigger = true;

		_state = AI.State.Idle;
	}

	private void Search(){
		if (_target == null) {
			//Debug.Log ("#Target is null#");
			_state = AI.State.Idle;
			if(_me.InCombat)
				_me.InCombat = false;

		} else {
			//Debug.Log ("########Serching#######");
			_state = AI.State.Decide;
			if(!_me.InCombat)
				_me.InCombat = true;
		}
	}

	private void Decide(){
		//Debug.Log ("########Decide#######");
		Move();

		int option = 0;
		if(_target != null && _target.CompareTag("Player")){
			//AI can do melee range and magic attacks
			if(Vector3.Distance(_myTransform.position, _target.position) < GameSetting.BASE_MELEE_RANGE && _me.meleeResetTimer <= 0){
			//	Debug.LogWarning("In Melee Range");
				option = Random.Range(0,3);
			}
			// he cannot use melee attacks
			else{
				if(_me.meleeResetTimer > 0)
					_me.meleeResetTimer -= Time.deltaTime;

			//	Debug.LogWarning("Not In Melee Range");
				option = Random.Range(1,3);
			}

			switch(option){
			case 0:
				MeleeAttack();
				break;
			case 1:
				RangedAttack();
				break;
			case 2:
				MagicAttack();
				break;
			default:
				Debug.Log("Option " + option + " is not defined");
				break;

				//Add cases for:
					//retreat - run to nearest mob
					//flee - run away from the player
					//
			}
		}

		_state = AI.State.Search;
	}
	private void MeleeAttack(){

		//set attackressettimer to the meleeattacktimer
		_me.meleeResetTimer = _me.meleeAttackTimer;
		//Deal with the animation
		SendMessage("MakeMeAttack",1,SendMessageOptions.RequireReceiver);
		if(true){
		//if hit
			PlayerCharacter.Instance.GetVital(0).CurValue -= 10;
			//PlayerCharacter.Instance.StatUpdate();
//			Debug.Log(PlayerCharacter.Instance.GetVital(0).CurValue);
			Messenger<int,int>.Broadcast("player health update", PlayerCharacter.Instance.GetVital(0).CurValue, PlayerCharacter.Instance.GetVital(0).AdjustedBaseValue,MessengerMode.DONT_REQUIRE_LISTENER);
			//Messenger<int,int>.Broadcast("mob health update",-10 ,100 ,MessengerMode.DONT_REQUIRE_LISTENER);
			// do something
			//Debug.Log("We Hit!");
		}
		else
		{
			//else
			// do something
			Debug.Log("We Miss!");

		}



		//meleeAttackTimer - the time it take between attacks
		//meleeResetTimer - the time left before we can attack again
		//meleeAttackSpeed - the speed the attack happens at
	}
	private void RangedAttack(){

	}
	private void MagicAttack(){
	
	}


	private void Move() {
		//Debug.Log ("########Move#######");
		if (_target) {
			float dist = Vector3.Distance (_target.position, _myTransform.position);

			if(_target.name == "Spawn Point"){
			//	Debug.LogWarning("Returning home" + dist);

				if(dist < GameSetting.BASE_MELEE_RANGE){
					_target = null;
					_state = AI.State.Idle;

					SendMessage ("MoveMeForward", Movement.Forward.none);			
					SendMessage ("RotateMe", Movement.Turn.none);
					return;
				}
			}
			//Will need to incoporate this new turning code in to the advanced movement script
			//one thing will have to do is lock the x axis so we do not tilt up or down
			Quaternion rot = Quaternion.LookRotation(_target.transform.position - _myTransform.position);
			_myTransform.rotation = Quaternion.Slerp(_myTransform.rotation, rot, Time.deltaTime * 5.0f);

			Vector3 dir = (_target.position - _myTransform.position).normalized;
			float direction = Vector3.Dot (dir, transform.forward);


	
			//almost infront of player
			if (direction > _FORWARD_DAMP && dist > GameSetting.BASE_MELEE_RANGE) {
				SendMessage ("MoveMeForward", Movement.Forward.forward);
			} else {
				SendMessage ("MoveMeForward", Movement.Forward.none);
			}


//			dir = (_target.position - _myTransform.position).normalized;
//			direction = Vector3.Dot (dir, transform.right);
//
//			if (direction > _ROTATION_DAMP) {
//				SendMessage ("RotateMe", AdvanceMovement.Turn.right);
//			} else if (direction < -_ROTATION_DAMP) {
//				SendMessage ("RotateMe", AdvanceMovement.Turn.left);
//			} else {
//				SendMessage ("RotateMe", AdvanceMovement.Turn.none);
//			}
		} 
		else {
			SendMessage ("MoveMeForward", Movement.Forward.none);			
			SendMessage ("RotateMe", Movement.Turn.none);

		}
	}

	public void OnTriggerEnter(Collider other){
		if (other.CompareTag ("Player")) {
			_target = other.transform;
			PlayerCharacter.Instance.InCombat = true;
			_state = AI.State.Search;
			StartCoroutine("FSM");
		}
	}
	public void OnTriggerExit(Collider other){
		if (other.CompareTag ("Player")) {
			_target = _home;
			PlayerCharacter.Instance.InCombat = false;
			if(_me.InCombat){
				_me.InCombat = false;
			}
		}
		Debug.LogWarning("3 - Combat: " + _me.InCombat);
	}
	
}
